home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / hity wydania / Ubuntu 9.10 PL / karmelkowy-koliberek-desktop-9.10-i386-PL.iso / casper / filesystem.squashfs / usr / lib / python2.6 / nntplib.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2009-11-11  |  21KB  |  683 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.6)
  3.  
  4. """An NNTP client class based on RFC 977: Network News Transfer Protocol.
  5.  
  6. Example:
  7.  
  8. >>> from nntplib import NNTP
  9. >>> s = NNTP('news')
  10. >>> resp, count, first, last, name = s.group('comp.lang.python')
  11. >>> print 'Group', name, 'has', count, 'articles, range', first, 'to', last
  12. Group comp.lang.python has 51 articles, range 5770 to 5821
  13. >>> resp, subs = s.xhdr('subject', first + '-' + last)
  14. >>> resp = s.quit()
  15. >>>
  16.  
  17. Here 'resp' is the server response line.
  18. Error responses are turned into exceptions.
  19.  
  20. To post an article from a file:
  21. >>> f = open(filename, 'r') # file containing article, including header
  22. >>> resp = s.post(f)
  23. >>>
  24.  
  25. For descriptions of all methods, read the comments in the code below.
  26. Note that all arguments and return values representing article numbers
  27. are strings, not numbers, since they are rarely used for calculations.
  28. """
  29. import re
  30. import socket
  31. __all__ = [
  32.     'NNTP',
  33.     'NNTPReplyError',
  34.     'NNTPTemporaryError',
  35.     'NNTPPermanentError',
  36.     'NNTPProtocolError',
  37.     'NNTPDataError',
  38.     'error_reply',
  39.     'error_temp',
  40.     'error_perm',
  41.     'error_proto',
  42.     'error_data']
  43.  
  44. class NNTPError(Exception):
  45.     '''Base class for all nntplib exceptions'''
  46.     
  47.     def __init__(self, *args):
  48.         Exception.__init__(self, *args)
  49.         
  50.         try:
  51.             self.response = args[0]
  52.         except IndexError:
  53.             self.response = 'No response given'
  54.  
  55.  
  56.  
  57.  
  58. class NNTPReplyError(NNTPError):
  59.     '''Unexpected [123]xx reply'''
  60.     pass
  61.  
  62.  
  63. class NNTPTemporaryError(NNTPError):
  64.     '''4xx errors'''
  65.     pass
  66.  
  67.  
  68. class NNTPPermanentError(NNTPError):
  69.     '''5xx errors'''
  70.     pass
  71.  
  72.  
  73. class NNTPProtocolError(NNTPError):
  74.     '''Response does not begin with [1-5]'''
  75.     pass
  76.  
  77.  
  78. class NNTPDataError(NNTPError):
  79.     '''Error in response data'''
  80.     pass
  81.  
  82. error_reply = NNTPReplyError
  83. error_temp = NNTPTemporaryError
  84. error_perm = NNTPPermanentError
  85. error_proto = NNTPProtocolError
  86. error_data = NNTPDataError
  87. NNTP_PORT = 119
  88. LONGRESP = [
  89.     '100',
  90.     '215',
  91.     '220',
  92.     '221',
  93.     '222',
  94.     '224',
  95.     '230',
  96.     '231',
  97.     '282']
  98. CRLF = '\r\n'
  99.  
  100. class NNTP:
  101.     
  102.     def __init__(self, host, port = NNTP_PORT, user = None, password = None, readermode = None, usenetrc = True):
  103.         """Initialize an instance.  Arguments:
  104.         - host: hostname to connect to
  105.         - port: port to connect to (default the standard NNTP port)
  106.         - user: username to authenticate with
  107.         - password: password to use with username
  108.         - readermode: if true, send 'mode reader' command after
  109.                       connecting.
  110.  
  111.         readermode is sometimes necessary if you are connecting to an
  112.         NNTP server on the local machine and intend to call
  113.         reader-specific comamnds, such as `group'.  If you get
  114.         unexpected NNTPPermanentErrors, you might need to set
  115.         readermode.
  116.         """
  117.         self.host = host
  118.         self.port = port
  119.         self.sock = socket.create_connection((host, port))
  120.         self.file = self.sock.makefile('rb')
  121.         self.debugging = 0
  122.         self.welcome = self.getresp()
  123.         readermode_afterauth = 0
  124.         if readermode:
  125.             
  126.             try:
  127.                 self.welcome = self.shortcmd('mode reader')
  128.             except NNTPPermanentError:
  129.                 pass
  130.             except NNTPTemporaryError:
  131.                 e = None
  132.                 if user and e.response[:3] == '480':
  133.                     readermode_afterauth = 1
  134.                 else:
  135.                     raise 
  136.                 e.response[:3] == '480'
  137.             
  138.  
  139.         None<EXCEPTION MATCH>NNTPPermanentError
  140.         
  141.         try:
  142.             if usenetrc and not user:
  143.                 import netrc as netrc
  144.                 credentials = netrc.netrc()
  145.                 auth = credentials.authenticators(host)
  146.                 if auth:
  147.                     user = auth[0]
  148.                     password = auth[2]
  149.                 
  150.         except IOError:
  151.             pass
  152.  
  153.         if user:
  154.             resp = self.shortcmd('authinfo user ' + user)
  155.             if resp[:3] == '381':
  156.                 if not password:
  157.                     raise NNTPReplyError(resp)
  158.                 password
  159.                 resp = self.shortcmd('authinfo pass ' + password)
  160.                 if resp[:3] != '281':
  161.                     raise NNTPPermanentError(resp)
  162.                 resp[:3] != '281'
  163.             
  164.             if readermode_afterauth:
  165.                 
  166.                 try:
  167.                     self.welcome = self.shortcmd('mode reader')
  168.                 except NNTPPermanentError:
  169.                     pass
  170.                 except:
  171.                     None<EXCEPTION MATCH>NNTPPermanentError
  172.                 
  173.  
  174.             None<EXCEPTION MATCH>NNTPPermanentError
  175.         
  176.  
  177.     
  178.     def getwelcome(self):
  179.         '''Get the welcome message from the server
  180.         (this is read and squirreled away by __init__()).
  181.         If the response code is 200, posting is allowed;
  182.         if it 201, posting is not allowed.'''
  183.         if self.debugging:
  184.             print '*welcome*', repr(self.welcome)
  185.         
  186.         return self.welcome
  187.  
  188.     
  189.     def set_debuglevel(self, level):
  190.         """Set the debugging level.  Argument 'level' means:
  191.         0: no debugging output (default)
  192.         1: print commands and responses but not body text etc.
  193.         2: also print raw lines read and sent before stripping CR/LF"""
  194.         self.debugging = level
  195.  
  196.     debug = set_debuglevel
  197.     
  198.     def putline(self, line):
  199.         '''Internal: send one line to the server, appending CRLF.'''
  200.         line = line + CRLF
  201.         if self.debugging > 1:
  202.             print '*put*', repr(line)
  203.         
  204.         self.sock.sendall(line)
  205.  
  206.     
  207.     def putcmd(self, line):
  208.         '''Internal: send one command to the server (through putline()).'''
  209.         if self.debugging:
  210.             print '*cmd*', repr(line)
  211.         
  212.         self.putline(line)
  213.  
  214.     
  215.     def getline(self):
  216.         '''Internal: return one line from the server, stripping CRLF.
  217.         Raise EOFError if the connection is closed.'''
  218.         line = self.file.readline()
  219.         if self.debugging > 1:
  220.             print '*get*', repr(line)
  221.         
  222.         if not line:
  223.             raise EOFError
  224.         line
  225.         if line[-2:] == CRLF:
  226.             line = line[:-2]
  227.         elif line[-1:] in CRLF:
  228.             line = line[:-1]
  229.         
  230.         return line
  231.  
  232.     
  233.     def getresp(self):
  234.         '''Internal: get a response from the server.
  235.         Raise various errors if the response indicates an error.'''
  236.         resp = self.getline()
  237.         if self.debugging:
  238.             print '*resp*', repr(resp)
  239.         
  240.         c = resp[:1]
  241.         if c == '4':
  242.             raise NNTPTemporaryError(resp)
  243.         c == '4'
  244.         if c == '5':
  245.             raise NNTPPermanentError(resp)
  246.         c == '5'
  247.         if c not in '123':
  248.             raise NNTPProtocolError(resp)
  249.         c not in '123'
  250.         return resp
  251.  
  252.     
  253.     def getlongresp(self, file = None):
  254.         '''Internal: get a response plus following text from the server.
  255.         Raise various errors if the response indicates an error.'''
  256.         openedFile = None
  257.         
  258.         try:
  259.             if isinstance(file, str):
  260.                 openedFile = file = open(file, 'w')
  261.             
  262.             resp = self.getresp()
  263.             if resp[:3] not in LONGRESP:
  264.                 raise NNTPReplyError(resp)
  265.             resp[:3] not in LONGRESP
  266.             list = []
  267.             while None:
  268.                 line = self.getline()
  269.                 if line == '.':
  270.                     break
  271.                 
  272.                 if line[:2] == '..':
  273.                     line = line[1:]
  274.                 
  275.                 if file:
  276.                     file.write(line + '\n')
  277.                     continue
  278.                 list.append(line)
  279.             if openedFile:
  280.                 openedFile.close()
  281.             
  282.             return (resp, list)
  283.  
  284.  
  285.     
  286.     def shortcmd(self, line):
  287.         '''Internal: send a command and get the response.'''
  288.         self.putcmd(line)
  289.         return self.getresp()
  290.  
  291.     
  292.     def longcmd(self, line, file = None):
  293.         '''Internal: send a command and get the response plus following text.'''
  294.         self.putcmd(line)
  295.         return self.getlongresp(file)
  296.  
  297.     
  298.     def newgroups(self, date, time, file = None):
  299.         """Process a NEWGROUPS command.  Arguments:
  300.         - date: string 'yymmdd' indicating the date
  301.         - time: string 'hhmmss' indicating the time
  302.         Return:
  303.         - resp: server response if successful
  304.         - list: list of newsgroup names"""
  305.         return self.longcmd('NEWGROUPS ' + date + ' ' + time, file)
  306.  
  307.     
  308.     def newnews(self, group, date, time, file = None):
  309.         """Process a NEWNEWS command.  Arguments:
  310.         - group: group name or '*'
  311.         - date: string 'yymmdd' indicating the date
  312.         - time: string 'hhmmss' indicating the time
  313.         Return:
  314.         - resp: server response if successful
  315.         - list: list of message ids"""
  316.         cmd = 'NEWNEWS ' + group + ' ' + date + ' ' + time
  317.         return self.longcmd(cmd, file)
  318.  
  319.     
  320.     def list(self, file = None):
  321.         '''Process a LIST command.  Return:
  322.         - resp: server response if successful
  323.         - list: list of (group, last, first, flag) (strings)'''
  324.         (resp, list) = self.longcmd('LIST', file)
  325.         for i in range(len(list)):
  326.             list[i] = tuple(list[i].split())
  327.         
  328.         return (resp, list)
  329.  
  330.     
  331.     def description(self, group):
  332.         """Get a description for a single group.  If more than one
  333.         group matches ('group' is a pattern), return the first.  If no
  334.         group matches, return an empty string.
  335.  
  336.         This elides the response code from the server, since it can
  337.         only be '215' or '285' (for xgtitle) anyway.  If the response
  338.         code is needed, use the 'descriptions' method.
  339.  
  340.         NOTE: This neither checks for a wildcard in 'group' nor does
  341.         it check whether the group actually exists."""
  342.         (resp, lines) = self.descriptions(group)
  343.         if len(lines) == 0:
  344.             return ''
  345.         return lines[0][1]
  346.  
  347.     
  348.     def descriptions(self, group_pattern):
  349.         '''Get descriptions for a range of groups.'''
  350.         line_pat = re.compile('^(?P<group>[^ \t]+)[ \t]+(.*)$')
  351.         (resp, raw_lines) = self.longcmd('LIST NEWSGROUPS ' + group_pattern)
  352.         if resp[:3] != '215':
  353.             (resp, raw_lines) = self.longcmd('XGTITLE ' + group_pattern)
  354.         
  355.         lines = []
  356.         for raw_line in raw_lines:
  357.             match = line_pat.search(raw_line.strip())
  358.             if match:
  359.                 lines.append(match.group(1, 2))
  360.                 continue
  361.         
  362.         return (resp, lines)
  363.  
  364.     
  365.     def group(self, name):
  366.         '''Process a GROUP command.  Argument:
  367.         - group: the group name
  368.         Returns:
  369.         - resp: server response if successful
  370.         - count: number of articles (string)
  371.         - first: first article number (string)
  372.         - last: last article number (string)
  373.         - name: the group name'''
  374.         resp = self.shortcmd('GROUP ' + name)
  375.         if resp[:3] != '211':
  376.             raise NNTPReplyError(resp)
  377.         resp[:3] != '211'
  378.         words = resp.split()
  379.         count = first = last = 0
  380.         n = len(words)
  381.         if n > 1:
  382.             count = words[1]
  383.             if n > 2:
  384.                 first = words[2]
  385.                 if n > 3:
  386.                     last = words[3]
  387.                     if n > 4:
  388.                         name = words[4].lower()
  389.                     
  390.                 
  391.             
  392.         
  393.         return (resp, count, first, last, name)
  394.  
  395.     
  396.     def help(self, file = None):
  397.         '''Process a HELP command.  Returns:
  398.         - resp: server response if successful
  399.         - list: list of strings'''
  400.         return self.longcmd('HELP', file)
  401.  
  402.     
  403.     def statparse(self, resp):
  404.         '''Internal: parse the response of a STAT, NEXT or LAST command.'''
  405.         if resp[:2] != '22':
  406.             raise NNTPReplyError(resp)
  407.         resp[:2] != '22'
  408.         words = resp.split()
  409.         nr = 0
  410.         id = ''
  411.         n = len(words)
  412.         if n > 1:
  413.             nr = words[1]
  414.             if n > 2:
  415.                 id = words[2]
  416.             
  417.         
  418.         return (resp, nr, id)
  419.  
  420.     
  421.     def statcmd(self, line):
  422.         '''Internal: process a STAT, NEXT or LAST command.'''
  423.         resp = self.shortcmd(line)
  424.         return self.statparse(resp)
  425.  
  426.     
  427.     def stat(self, id):
  428.         '''Process a STAT command.  Argument:
  429.         - id: article number or message id
  430.         Returns:
  431.         - resp: server response if successful
  432.         - nr:   the article number
  433.         - id:   the message id'''
  434.         return self.statcmd('STAT ' + id)
  435.  
  436.     
  437.     def next(self):
  438.         '''Process a NEXT command.  No arguments.  Return as for STAT.'''
  439.         return self.statcmd('NEXT')
  440.  
  441.     
  442.     def last(self):
  443.         '''Process a LAST command.  No arguments.  Return as for STAT.'''
  444.         return self.statcmd('LAST')
  445.  
  446.     
  447.     def artcmd(self, line, file = None):
  448.         '''Internal: process a HEAD, BODY or ARTICLE command.'''
  449.         (resp, list) = self.longcmd(line, file)
  450.         (resp, nr, id) = self.statparse(resp)
  451.         return (resp, nr, id, list)
  452.  
  453.     
  454.     def head(self, id):
  455.         """Process a HEAD command.  Argument:
  456.         - id: article number or message id
  457.         Returns:
  458.         - resp: server response if successful
  459.         - nr: article number
  460.         - id: message id
  461.         - list: the lines of the article's header"""
  462.         return self.artcmd('HEAD ' + id)
  463.  
  464.     
  465.     def body(self, id, file = None):
  466.         """Process a BODY command.  Argument:
  467.         - id: article number or message id
  468.         - file: Filename string or file object to store the article in
  469.         Returns:
  470.         - resp: server response if successful
  471.         - nr: article number
  472.         - id: message id
  473.         - list: the lines of the article's body or an empty list
  474.                 if file was used"""
  475.         return self.artcmd('BODY ' + id, file)
  476.  
  477.     
  478.     def article(self, id):
  479.         '''Process an ARTICLE command.  Argument:
  480.         - id: article number or message id
  481.         Returns:
  482.         - resp: server response if successful
  483.         - nr: article number
  484.         - id: message id
  485.         - list: the lines of the article'''
  486.         return self.artcmd('ARTICLE ' + id)
  487.  
  488.     
  489.     def slave(self):
  490.         '''Process a SLAVE command.  Returns:
  491.         - resp: server response if successful'''
  492.         return self.shortcmd('SLAVE')
  493.  
  494.     
  495.     def xhdr(self, hdr, str, file = None):
  496.         """Process an XHDR command (optional server extension).  Arguments:
  497.         - hdr: the header type (e.g. 'subject')
  498.         - str: an article nr, a message id, or a range nr1-nr2
  499.         Returns:
  500.         - resp: server response if successful
  501.         - list: list of (nr, value) strings"""
  502.         pat = re.compile('^([0-9]+) ?(.*)\n?')
  503.         (resp, lines) = self.longcmd('XHDR ' + hdr + ' ' + str, file)
  504.         for i in range(len(lines)):
  505.             line = lines[i]
  506.             m = pat.match(line)
  507.             if m:
  508.                 lines[i] = m.group(1, 2)
  509.                 continue
  510.         
  511.         return (resp, lines)
  512.  
  513.     
  514.     def xover(self, start, end, file = None):
  515.         '''Process an XOVER command (optional server extension) Arguments:
  516.         - start: start of range
  517.         - end: end of range
  518.         Returns:
  519.         - resp: server response if successful
  520.         - list: list of (art-nr, subject, poster, date,
  521.                          id, references, size, lines)'''
  522.         (resp, lines) = self.longcmd('XOVER ' + start + '-' + end, file)
  523.         xover_lines = []
  524.         for line in lines:
  525.             elem = line.split('\t')
  526.             
  527.             try:
  528.                 xover_lines.append((elem[0], elem[1], elem[2], elem[3], elem[4], elem[5].split(), elem[6], elem[7]))
  529.             continue
  530.             except IndexError:
  531.                 raise NNTPDataError(line)
  532.                 continue
  533.             
  534.  
  535.         
  536.         return (resp, xover_lines)
  537.  
  538.     
  539.     def xgtitle(self, group, file = None):
  540.         '''Process an XGTITLE command (optional server extension) Arguments:
  541.         - group: group name wildcard (i.e. news.*)
  542.         Returns:
  543.         - resp: server response if successful
  544.         - list: list of (name,title) strings'''
  545.         line_pat = re.compile('^([^ \t]+)[ \t]+(.*)$')
  546.         (resp, raw_lines) = self.longcmd('XGTITLE ' + group, file)
  547.         lines = []
  548.         for raw_line in raw_lines:
  549.             match = line_pat.search(raw_line.strip())
  550.             if match:
  551.                 lines.append(match.group(1, 2))
  552.                 continue
  553.         
  554.         return (resp, lines)
  555.  
  556.     
  557.     def xpath(self, id):
  558.         '''Process an XPATH command (optional server extension) Arguments:
  559.         - id: Message id of article
  560.         Returns:
  561.         resp: server response if successful
  562.         path: directory path to article'''
  563.         resp = self.shortcmd('XPATH ' + id)
  564.         if resp[:3] != '223':
  565.             raise NNTPReplyError(resp)
  566.         resp[:3] != '223'
  567.         
  568.         try:
  569.             (resp_num, path) = resp.split()
  570.         except ValueError:
  571.             raise NNTPReplyError(resp)
  572.  
  573.         return (resp, path)
  574.  
  575.     
  576.     def date(self):
  577.         '''Process the DATE command. Arguments:
  578.         None
  579.         Returns:
  580.         resp: server response if successful
  581.         date: Date suitable for newnews/newgroups commands etc.
  582.         time: Time suitable for newnews/newgroups commands etc.'''
  583.         resp = self.shortcmd('DATE')
  584.         if resp[:3] != '111':
  585.             raise NNTPReplyError(resp)
  586.         resp[:3] != '111'
  587.         elem = resp.split()
  588.         if len(elem) != 2:
  589.             raise NNTPDataError(resp)
  590.         len(elem) != 2
  591.         date = elem[1][2:8]
  592.         time = elem[1][-6:]
  593.         if len(date) != 6 or len(time) != 6:
  594.             raise NNTPDataError(resp)
  595.         len(time) != 6
  596.         return (resp, date, time)
  597.  
  598.     
  599.     def post(self, f):
  600.         '''Process a POST command.  Arguments:
  601.         - f: file containing the article
  602.         Returns:
  603.         - resp: server response if successful'''
  604.         resp = self.shortcmd('POST')
  605.         if resp[0] != '3':
  606.             raise NNTPReplyError(resp)
  607.         resp[0] != '3'
  608.         while None:
  609.             line = f.readline()
  610.             if not line:
  611.                 break
  612.             
  613.             if line[-1] == '\n':
  614.                 line = line[:-1]
  615.             
  616.             if line[:1] == '.':
  617.                 line = '.' + line
  618.             
  619.             continue
  620.             self.putline('.')
  621.             return self.getresp()
  622.  
  623.     
  624.     def ihave(self, id, f):
  625.         '''Process an IHAVE command.  Arguments:
  626.         - id: message-id of the article
  627.         - f:  file containing the article
  628.         Returns:
  629.         - resp: server response if successful
  630.         Note that if the server refuses the article an exception is raised.'''
  631.         resp = self.shortcmd('IHAVE ' + id)
  632.         if resp[0] != '3':
  633.             raise NNTPReplyError(resp)
  634.         resp[0] != '3'
  635.         while None:
  636.             line = f.readline()
  637.             if not line:
  638.                 break
  639.             
  640.             if line[-1] == '\n':
  641.                 line = line[:-1]
  642.             
  643.             if line[:1] == '.':
  644.                 line = '.' + line
  645.             
  646.             continue
  647.             self.putline('.')
  648.             return self.getresp()
  649.  
  650.     
  651.     def quit(self):
  652.         '''Process a QUIT command and close the socket.  Returns:
  653.         - resp: server response if successful'''
  654.         resp = self.shortcmd('QUIT')
  655.         self.file.close()
  656.         self.sock.close()
  657.         del self.file
  658.         del self.sock
  659.         return resp
  660.  
  661.  
  662. if __name__ == '__main__':
  663.     import os
  664.     if 'news':
  665.         pass
  666.     newshost = os.environ['NNTPSERVER']
  667.     if newshost.find('.') == -1:
  668.         mode = 'readermode'
  669.     else:
  670.         mode = None
  671.     s = NNTP(newshost, readermode = mode)
  672.     (resp, count, first, last, name) = s.group('comp.lang.python')
  673.     print resp
  674.     print 'Group', name, 'has', count, 'articles, range', first, 'to', last
  675.     (resp, subs) = s.xhdr('subject', first + '-' + last)
  676.     print resp
  677.     for item in subs:
  678.         print '%7s %s' % item
  679.     
  680.     resp = s.quit()
  681.     print resp
  682.  
  683.